package main

import (
	"context"
	"google.golang.org/grpc/credentials"
	"log"
	"net"
	"time"

	"google.golang.org/grpc"
	pb "linclaus.com/cmd/grpc/hello" // 替换为实际的包路径
)

// 实现 Greeter 服务
type server struct {
	pb.UnimplementedGreeterServer
}

// 实现 SayHello 方法
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloResponse{Message: "Hello " + in.GetName()}, nil
}

// 服务端流式 RPC 实现
func (s *server) SayHelloStream(in *pb.HelloRequest, stream pb.Greeter_SayHelloStreamServer) error {
	log.Printf("Streaming for: %v", in.GetName())

	// 发送3条消息
	for i := 0; i < 3; i++ {
		if err := stream.Send(&pb.HelloResponse{Message: "Hello " + in.GetName() + " - " + time.Now().String()}); err != nil {
			return err
		}
		time.Sleep(time.Second)
	}
	return nil
}

// 客户端流式 RPC 实现
func (s *server) SayHelloClientStream(stream pb.Greeter_SayHelloClientStreamServer) error {
	var names []string

	// 接收所有客户端消息
	for {
		in, err := stream.Recv()
		if err != nil {
			break
		}
		names = append(names, in.GetName())
		log.Printf("Received: %v", in.GetName())
	}

	// 返回合并后的消息
	return stream.SendAndClose(&pb.HelloResponse{
		Message: "Hello to " + joinNames(names),
	})
}

// 双向流式 RPC 实现
func (s *server) SayHelloBidiStream(stream pb.Greeter_SayHelloBidiStreamServer) error {
	// 启动一个 goroutine 处理客户端消息
	go func() {
		for {
			in, err := stream.Recv()
			if err != nil {
				return
			}
			log.Printf("Received in stream: %v", in.GetName())

			// 发送响应
			if err := stream.Send(&pb.HelloResponse{Message: "Hello " + in.GetName()}); err != nil {
				log.Printf("Error sending response: %v", err)
				return
			}
		}
	}()

	// 等待客户端关闭流
	<-stream.Context().Done()
	return stream.Context().Err()
}

// 辅助函数
func joinNames(names []string) string {
	if len(names) == 0 {
		return ""
	}
	if len(names) == 1 {
		return names[0]
	}
	return names[0] + " and " + names[1]
}

func main() {
	lis, err := net.Listen("tcp", ":50051")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	// 创建 gRPC 服务器并注册服务
	// openssl genrsa -out ca.key 2048
	// openssl req -new -x509 -key ca.key -out ca.crt -days 3650 -subj "/CN=server.example.com"
	// openssl genrsa -out server.key 2048
	// openssl req -new -key server.key -out server.csr -subj "/CN=server.example.com"
	// echo "subjectAltName = DNS:server.example.com" > extfile.cnf
	// openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -extfile extfile.cnf
	creds, err := credentials.NewServerTLSFromFile("certs/server.crt", "certs/server.key")
	if err != nil {
		log.Fatalf("failed to create credentials: %v", err)
	}
	s := grpc.NewServer(grpc.Creds(creds))
	//s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Println("Server is listening on port 50051")
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}
